#!/usr/bin/env python
# xml tree <--> sqltree converter

# $Id$
"""
Pack data.

"""
import sys
from main_utils import *

def pack_names ( options ) :
    options.cursor.execute ( """
    update attr_pair set name_id = to_id 
    from 
    (
    select name.name_id as from_id , 
    uniq_names.name_id as to_id 
    from
    ( select distinct on (name) * from name ) 
    as uniq_names
    join name using(name)
    where uniq_names.name_id != name.name_id 
    ) as trans_table
    where name_id = from_id
    ;
    delete from name where not exists 
    ( select 1 from attr_pair 
    where attr_pair.name_id=name.name_id ) ;
    """ )

def pack_values ( options ) :
    options.cursor.execute ( """
    update attr_pair set value_id = to_id 
    from 
    (
    select value.value_id as from_id , 
    uniq_values.value_id as to_id 
    from
    ( select distinct on (value) * from value ) 
    as uniq_values
    join value using(value)
    where uniq_values.value_id != value.value_id 
    ) as trans_table
    where value_id = from_id
    ;
    delete from value where not exists
    ( select 1 from attr_pair 
    where attr_pair.value_id=value.value_id ) ;
    """ )

def pack_pairs ( options ) :
    options.cursor.execute ( """
    update attr_list set attr_pair = to_id 
    from 
    (
    select attr_pair.attr_pair as from_id , 
    uniq_attr_pairs.attr_pair as to_id 
    from
    ( select distinct on (name_id,value_id) * 
    from attr_pair ) as uniq_attr_pairs
    join attr_pair using(name_id,value_id)
    where uniq_attr_pairs.attr_pair != attr_pair.attr_pair
    ) as trans_table
    where attr_pair = from_id
    ;
    delete from attr_pair where not exists 
    ( select 1 from attr_list 
    where attr_list.attr_pair=attr_pair.attr_pair ) ;
    """ )

def pack_lists ( options ) :
    raise NotImplementedError

def pack_trees ( options ) :
    raise NotImplementedError

def pack_tables ( options ) :
    raise NotImplementedError

def pack_vacuum ( options ) :
    connect ( options )
    options.conn.autocommit(1)
    cr = options.conn.cursor()
    cr.execute ( 'vacuum full analyze' )
    options.conn.close()

pack_utils = [ ('names',pack_names), ('values',pack_values),
               ('pairs',pack_pairs), #('lists',pack_lists),
               #('trees',pack_trees), ('tables',pack_tables)
               ]

def pack ( options ) :
    connect ( options )
    cr = options.cursor = options.conn.cursor()
    cr.execute('set transaction isolation level serializable')
    cr.execute ( 'set search_path to '+options.schema )
    if not options.quiet :
        print 'Sizes before:'
        print '-------------'
        show_sizes ( options )
    if options.pack == 'all' :
        for n,r in pack_utils : r ( options )
    else : filter(lambda (x,y) : x==options.pack , pack_utils)[0][1]( options )
    if not options.quiet :
        print 'Sizes after:'
        print '------------'
        show_sizes ( options )
    disconnect ( options )
    pack_vacuum ( options )
#===========================================================
